//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package com.kalvan.web.excel;

import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.context.WriteContext;
import com.alibaba.excel.event.WriteHandler;
import com.alibaba.excel.exception.ExcelGenerateException;
import com.alibaba.excel.metadata.BaseRowModel;
import com.alibaba.excel.metadata.ExcelColumnProperty;
import com.alibaba.excel.metadata.Sheet;
import com.alibaba.excel.metadata.Table;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.alibaba.excel.util.CollectionUtils;
import com.alibaba.excel.util.POITempFile;
import com.alibaba.excel.util.TypeUtil;
import com.alibaba.excel.util.WorkBookUtil;
import com.alibaba.excel.write.ExcelBuilder;
import com.kalvan.sensitive.annotation.Desensitized;
import com.kalvan.sensitive.utils.SensitiveInfoUtils;
import com.kalvan.web.dict.CacheUtil;
import com.kalvan.web.excel.annotation.Dict;
import com.kalvan.web.excel.annotation.ExtSuffix;
import com.kalvan.web.excel.annotation.NumberConvert;
import net.sf.cglib.beans.BeanMap;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.util.CellRangeAddress;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.text.DecimalFormat;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

public class ExcelBuilderImpl implements ExcelBuilder {
    private WriteContext context;

    public ExcelBuilderImpl(InputStream templateInputStream, OutputStream out, ExcelTypeEnum excelType, boolean needHead, WriteHandler writeHandler) {
        try {
            POITempFile.createPOIFilesDirectory();
            this.context = new WriteContext(templateInputStream, out, excelType, needHead, writeHandler);
        } catch (Exception var7) {
            throw new RuntimeException(var7);
        }
    }

    public void addContent(List data, int startRow) {
        if (!CollectionUtils.isEmpty(data)) {
            int rowNum = this.context.getCurrentSheet().getLastRowNum();
            if (rowNum == 0) {
                Row row = this.context.getCurrentSheet().getRow(0);
                if (row == null && (this.context.getExcelHeadProperty() == null || !this.context.needHead())) {
                    rowNum = -1;
                }
            }

            if (rowNum < startRow) {
                rowNum = startRow;
            }

            for (int i = 0; i < data.size(); ++i) {
                int n = i + rowNum + 1;
                this.addOneRowOfDataToExcel(data.get(i), n);
            }

        }
    }

    Map<String, Dict> dictField = new HashMap();
    Map<String, NumberConvert> numberConvertField = new HashMap();
    Map<String, ExtSuffix> extSuffixField = new HashMap<String, ExtSuffix>();
    Map<String, Desensitized> desensitizedField = new HashMap<String, Desensitized>();

    public void addContent(List data, Sheet sheetParam) {
        // by kalvan 增加导出数据的转换
        Field[] fields = sheetParam.getClazz().getDeclaredFields();
        for (Field field : fields) {
            if (field.getAnnotation(ExcelProperty.class) == null) {
                // throw new RuntimeException("@ExtExcel 只能用在@Excel字段上");
                continue;
            }
            // 字典转换
            if (field.getAnnotation(Dict.class) != null) {
                dictField.put(field.getName(), field.getAnnotation(Dict.class));
            }
            // 数字转换
            if (field.getAnnotation(NumberConvert.class) != null) {
                numberConvertField.put(field.getName(), field.getAnnotation(NumberConvert.class));
            }
            // 拼接内容
            if (field.getAnnotation(ExtSuffix.class) != null) {
                extSuffixField.put(field.getName(), field.getAnnotation(ExtSuffix.class));
            }
            // 脱敏导出
            if (field.getAnnotation(Desensitized.class) != null) {
                desensitizedField.put(field.getName(), field.getAnnotation(Desensitized.class));
            }
        }
        this.context.currentSheet(sheetParam);
        this.addContent(data, sheetParam.getStartRow());
    }

    public void addContent(List data, Sheet sheetParam, Table table) {
        this.context.currentSheet(sheetParam);
        this.context.currentTable(table);
        this.addContent(data, sheetParam.getStartRow());
    }

    public void merge(int firstRow, int lastRow, int firstCol, int lastCol) {
        CellRangeAddress cra = new CellRangeAddress(firstRow, lastRow, firstCol, lastCol);
        this.context.getCurrentSheet().addMergedRegion(cra);
    }

    public void finish() {
        try {
            this.context.getWorkbook().write(this.context.getOutputStream());
            this.context.getWorkbook().close();
        } catch (IOException var2) {
            throw new ExcelGenerateException("IO error", var2);
        }
    }

    private void addBasicTypeToExcel(List<Object> oneRowData, Row row) {
        if (!CollectionUtils.isEmpty(oneRowData)) {
            for (int i = 0; i < oneRowData.size(); ++i) {
                Object cellValue = oneRowData.get(i);
                Cell cell = WorkBookUtil.createCell(row, i, this.context.getCurrentContentStyle(), cellValue, TypeUtil.isNum(cellValue));
                if (null != this.context.getAfterWriteHandler()) {
                    this.context.getAfterWriteHandler().cell(i, cell);
                }
            }

        }
    }

    private void addJavaObjectToExcel(Object oneRowData, Row row) {
        int i = 0;
        BeanMap beanMap = BeanMap.create(oneRowData);

        for (Iterator var5 = this.context.getExcelHeadProperty().getColumnPropertyList().iterator(); var5.hasNext(); ++i) {
            ExcelColumnProperty excelHeadProperty = (ExcelColumnProperty) var5.next();
            BaseRowModel baseRowModel = (BaseRowModel) oneRowData;
            String cellValue = TypeUtil.getFieldStringValue(beanMap, excelHeadProperty.getField().getName(), excelHeadProperty.getFormat());
            // by kalvan 转换数据
            cellValue = getValue(excelHeadProperty.getField().getName(), cellValue);

            CellStyle cellStyle = baseRowModel.getStyle(i) != null ? baseRowModel.getStyle(i) : this.context.getCurrentContentStyle();
//            Cell cell = WorkBookUtil.createCell(row, i, cellStyle, cellValue, TypeUtil.isNum(excelHeadProperty.getField()));
            Cell cell = WorkBookUtil.createCell(row, i, cellStyle, cellValue, false);
            if (null != this.context.getAfterWriteHandler()) {
                this.context.getAfterWriteHandler().cell(i, cell);
            }
        }

    }

    protected String getValue(String fieldName, String originValue) {
        String value = originValue;
        Dict dict = dictField.get(fieldName);
        NumberConvert numberConvert = numberConvertField.get(fieldName);
        ExtSuffix extSuffix = extSuffixField.get(fieldName);
        Desensitized desensitized = desensitizedField.get(fieldName);
        if (dict != null) {
            value = CacheUtil.getCache().getDictValue(dict.value(), originValue + "");
            if (StringUtils.isBlank(value.toString()) && originValue != null
                    && StringUtils.isNotBlank(originValue + "")) {
                // 没有转换则显示原值
                value = originValue;
            }
        }
        if (numberConvert != null) {
            Double number = Double.parseDouble(value);
            String precisionBit = StringUtils.rightPad("0.", numberConvert.precisionBit() + 2, "#");
            DecimalFormat decimalFormat = new DecimalFormat(precisionBit);
            value = decimalFormat.format(number / numberConvert.value());
        }
        if (extSuffix != null) {
            value = value + extSuffix.value();
        }
        if (desensitized != null) {
            value = SensitiveInfoUtils.convertMsg(desensitized.type(), value + "");
        }
        return value;
    }

    private void addOneRowOfDataToExcel(Object oneRowData, int n) {
        Row row = WorkBookUtil.createRow(this.context.getCurrentSheet(), n);
        if (null != this.context.getAfterWriteHandler()) {
            this.context.getAfterWriteHandler().row(n, row);
        }

        if (oneRowData instanceof List) {
            this.addBasicTypeToExcel((List) oneRowData, row);
        } else {
            this.addJavaObjectToExcel(oneRowData, row);
        }

    }
}
